public class IntSequence implements Cloneable
{
  private int[] data;
  private int manyItems;
        
  public IntSequence ()
  {
    final int INITIAL_CAPACITY = 10;
    manyItems = 0;
    data = new int [INITIAL_CAPACITY];
  }
  
  public IntSequence (int initialCapacity)
  {
    if( initialCapacity < 0)
      throw new IllegalArgumentException ("initialCapacity < 0");
      
    manyItems = 0;
    data = new int [initialCapacity];
  }
  
  public void add (int element)
  {
    if( manyItems == data.length )
      ensureCapacity (manyItems * 2 + 1);
      
    data[manyItems] = element;
    manyItems ++;
  }
  
  public void addAll (IntSequence addend)
  {
    ensureCapacity (manyItems + addend.manyItems);
    
    System.arraycopy (addend.data, 0, data, manyItems, addend.manyItems);
    manyItems += addend.manyItems;
  }
  
  public Object clone ()
  {
    IntSequence answer;
    
    try
    {
      answer = (IntSequence) super.clone ();
    }
    catch( CloneNotSupportedException e)
    {
      throw new RuntimeException ("implements Cloneable forgotten");
    }
    
    answer.data = (int[]) data.clone ();
    
    return answer;
  }
  
  public int countOccurences (int target)
  {
    int answer;
    int index;
    
    answer = 0;
    for( index = 0 ; index < manyItems ; index ++)
      if( target == data[index] )
          answer ++;
          
    return answer;
  }
  
  public void ensureCapacity (int minimumCapacity)
  {
    int[] biggerArray;
    
    if( data.length < minimumCapacity )
    {
      biggerArray = new int[minimumCapacity];
      System.arraycopy (data, 0, biggerArray, 0, manyItems);
      data = biggerArray;
    }
  }
  
  public int getCapacity ()
  {
    return data.length;
  }
  
  public int size ()
  {
    return manyItems;
  }
  
  public boolean remove (int target)
  {
    int index = 0;
    
    while( index < manyItems && target != data[index] )
      index ++;
      
    if( index == manyItems )
      return false;
      
    manyItems --;
    data[index] = data[manyItems];
    
    return true;
  }
  
  public void trimToSize ()
  {
    int[] trimmedArray;
    
    if( data.length > manyItems )
    {
      trimmedArray = new int [manyItems];
      System.arraycopy (data, 0, trimmedArray, 0, manyItems);
      data = trimmedArray;
    }
  }
  
  public static IntSequence union (IntSequence b1, IntSequence b2)
  {
    IntSequence answer = new IntSequence (b1.getCapacity () + b2.getCapacity ());
    
    System.arraycopy (b1.data, 0, answer, 0, b1.manyItems);
    System.arraycopy (b2.data, 0, answer, b1.manyItems, b2.manyItems);
    answer.manyItems = b1.manyItems + b2.manyItems;
    
    return answer;
  }
}

// Teme
// Laborator
// 1. Pentru clasa IntSequence, implementati o metoda de tiparire
//    astfel ca la:
//
//    IntSequence s (10);
//    System.out.println (s);
//
//    sa se tipareasca toate valorile stocate in secventa.
//
// 2. Realizati o metoda main () in care sa instantiati clasa IntSequence
//    si sa introduceti trei elemente. Apoi tipariti-le. Stergeti un element
//    si tipariti din nou elementele ramase.
//
// 3. Modificati sursa clasei astfel incat elementele:
//    * sa fie mentinute intotdeauna in ordine crescatoare;
//    * sa nu mai existe elemente duplicate.
//
// Casa
//
// 4. Realizati o clasa Polinom care implementeaza lucrul cu polinoame.
//    Clasa va memora coeficientii polinomului si va calcula valoarea lui
//    pentru diferite argumente. Clasa va trebui sa implementeze metodele:
//    * public Polinom ()
//    	- constructor implicit
//    * public Polinom (double a0)
//	- constructor ce initializeaza numai coeficientul de grad 0
//    * public Polinom (Polinom sursa)
//	- copiaza identic un alt polinom
//    * public Object clone ()
//	- crearea unei copii identice
//    * public void add_to_coef (double amount, int k)
//	- adunarea unei valori la coeficientul de grad k
//    * public void assign_to_coef (double coef, int k)
//	- modificarea valorii coeficientului de grad k
//    * public void clear ()
//	- resetarea valorilor tuturor coeficientilor
//    * public void reserve (int k)
//	- rezervarea de spatiu pentru un polinom de grad cel mult k
//    * public double coefficient (int k)
//	- intoarce coeficientul de grad k
//    * public int degree ()
//	- intoarce gradul polinomului
//    * public double eval (double x)
//	- evalueaza polinomul pentru argumentul x
//    * public static Polinom sumation (Polinom p1, Polinom p2)
//	- realizeaza suma a doua polinoame
//    * public static Polinom product (Polinom p1, Polinom p2)
//	- produsul a doua polinoame
// 5. Realizati o clasa noua PlinomDemo ce instantiaza clasa Polinom
//    Implementati 3 exemple:
//    a) Creati doua polinoame
//    b) Creati un al treilea polinom, clona a primului
//    c) Realizati suma celor doua plonioame
//    d) Realizati produsul intre rezultatul sumei si polinomul clonat
//
// Imi veti prezenta cele doua surse, IntSequence.java modificat si Polinom.java in cadrul 
// laboratorului.
// Cum va voi nota:
// - daca tema intarzie mai mult de doua saptamani nu o mai consider;
// - daca nu se compileaza nu ma uit peste ele;
// - verific functionalitatea pe un exemplu ales de mine. Daca nu functioneaza
// conform asteptarilor, va scad 1p, va trimit sursele inapoi urmand ca voi sa
// corectati si imi trimiteti inapoi, urmind ca eu sa aplic acelasi procedeu pana tema
// va merge corect; fiecare corectura costa.
// - temele duplicat sau aproape identice le voi colecta si voi imparti nota la numarul autorilor.